home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1833 / 1833.xpi / chrome / yoono.jar / content / yoono / bookmarks / bookmarksxopml.js < prev    next >
Text File  |  2009-12-16  |  16KB  |  535 lines

  1. /*
  2.  * bookmarksxbel.js
  3.  *
  4.  * @author    david marteau <marteau.david@free.fr>
  5.  * @copyright 2005-2006 Yoono
  6.  */
  7.  
  8.  
  9. function ynListOfLinks( aBaseURI )
  10. {
  11.   this.baseURI = aBaseURI;
  12.   this.links   = [];
  13. }
  14.  
  15. ynListOfLinks.prototype =
  16. {
  17.   copy : function( aBaseURI ) 
  18.   {
  19.     var newList = new ynListOfLinks(aBaseURI);
  20.     for(var i=0;i<this.links.length;++i)
  21.         newList.append(this.links[i]);
  22.         
  23.     return newList;
  24.   },
  25.  
  26.   append : function( aURI ) {
  27.     this.links.push(aURI);
  28.   },
  29.   
  30.   contains : function( aURI ) 
  31.   {
  32.     for(var i=0;i<this.links.length;++i) {
  33.        if(this.links[i].equals(aURI))
  34.           return true;
  35.     }
  36.     return false;
  37.   },
  38.   
  39.   get spec() { return this.baseURI.spec; },
  40.   
  41.   toString : function() 
  42.   {
  43.     var str = "base URI: "+ this.baseURI.spec + "\n";
  44.     for(var i=0;i<this.links.length;++i) {
  45.       str += i+". "+this.links[i].spec+"\n";
  46.     } 
  47.     return str;
  48.   }
  49.   
  50. };
  51.  
  52.  
  53. //====================================================
  54. // OPML Driver
  55. //====================================================
  56.  
  57.  function ynOPMLIOService() 
  58.  {
  59.    this._bmUtils = new ynBookmarksUtils();
  60.    this._yns     = new Namespace(YOONO_NS);
  61.    this._owner   = "firefox-yoono-extension";
  62.  
  63.    this._ioSrvc   = Components.classes["@mozilla.org/network/io-service;1"]
  64.                     .getService(Components.interfaces.nsIIOService);
  65.  
  66.    this._allowDuplicateURL = this._bmUtils.getPref("extensions.yoono.import.allowDuplicateURL",false );
  67.    this._allowRemoteURL    = this._bmUtils.getPref("extensions.yoono.import.allowRemoteURL"   ,false);
  68.  }
  69.  
  70.  ynOPMLIOService.prototype =
  71.  {
  72.  
  73.   /*
  74.    * import xbel xmlObject in  'root' folder
  75.    */
  76.    _import : function( opmlBody, root, rootLinks )
  77.    {
  78.      var foldersets=[[opmlBody,root,rootLinks]];
  79.      var folderset=null;
  80.  
  81.      var bmUtils   = this._bmUtils;
  82.      var yns       = this._yns;
  83.      var owner     = this._owner;
  84.      var duplicate = this._allowDuplicateURL;
  85.      var remote    = this._allowRemoteURL; 
  86.     
  87.      var opmlFileExt = /\.opml$/;
  88.  
  89.      const urlRes  = bmUtils.getArc("URL");
  90.      const nameRes = bmUtils.getArc("Name");
  91.  
  92.      /*
  93.       * Import node as folder, handle replication
  94.       */
  95.       
  96.      function importAsFolder( opml, text, description, parent, returned )
  97.      {
  98.        var res      = null; 
  99.        var resource = null;
  100.           
  101.        // Find the parent folder if no duplicate allowed
  102.        // Otherwise just add a new folder
  103.  
  104.        if(!duplicate)  // No duplicate allowed
  105.            resource = bmUtils.getBookmarkedResource(nameRes,text);
  106.        
  107.        if(!resource)
  108.        {
  109.          // XXX Need to set parent for setting description       
  110.          res =  resource = (description ? 
  111.                    bmUtils.createFolder(text,description,parent) :
  112.                    bmUtils.createFolder(text,null,null));
  113.        }
  114.  
  115.        if(opml && resource)
  116.           foldersets.push([opml,resource,returned.links]);
  117.           
  118.        if(returned)
  119.           returned.value = resource;
  120.           
  121.        return res; 
  122.      }     
  123.      
  124.      /*
  125.       * Preload links
  126.       */
  127.  
  128.      var resourcesLinks = this._resourcesLinks;
  129.      var ioSrvc         = this._ioSrvc;
  130.  
  131.      function preLoadLink( url,text,description,parent, folderLinks )
  132.      {
  133.        bmUtils.error("yoono:opml","preload :"+url+"\n"+folderLinks.toString());
  134.  
  135.        // Only link to local file allowed
  136.        if(!remote && url.substr(0,5)!= "file:") {
  137.            bmUtils.error("yoono:opml","remote file dropped\n"+url);
  138.            return null;
  139.        }
  140.  
  141.        var uri = ioSrvc.newURI(url, null, null);
  142.        
  143.        // Check for recursivity        
  144.        if(folderLinks && folderLinks.contains(uri)) {
  145.           bmUtils.error("yoono:opml","recursive link dropped\n"+uri.spec);
  146.           return null;
  147.        }
  148.  
  149.        if(folderLinks)
  150.           folderLinks = folderLinks.copy(uri);
  151.        else 
  152.           folderLinks = new ynListOfLinks(uri);
  153.  
  154.        folderLinks.append(uri);
  155.  
  156.        var returned = { links: folderLinks };
  157.        var res = importAsFolder(null,text,description,parent,returned);
  158.      
  159.        if(returned.value) 
  160.           resourcesLinks.push([folderLinks,returned.value]);
  161.           
  162.        return res;
  163.      }
  164.  
  165.      // Loop over folders
  166.  
  167.      while(foldersets.length>0)
  168.      {
  169.        folderset=foldersets.shift();
  170.     
  171.        var folder      = folderset[0];
  172.        var parent      = folderset[1];
  173.        var folderLinks = folderset[2];
  174.  
  175.        var parentContainer = bmUtils.getContainer(parent);
  176.        var numItems = 0; 
  177.                  
  178.        // Loop over child nodes
  179.                                 
  180.        for each (var element in folder.outline) 
  181.        {
  182.          var res = null;
  183.   
  184.          var text        = element.@text.toString();
  185.          var description = element.@description.toString();
  186.  
  187.          switch(element.@type.toString())
  188.          {
  189.            case "include" : {
  190.              var url = element.@url.toString();
  191.              res = preLoadLink( url,text,description,parent,folderLinks );
  192.              if(res) numItems++;
  193.            } break;
  194.  
  195.            case "link": {
  196.              var url = element.@url.toString();
  197.              if(url.match(opmlFileExt))
  198.              {
  199.                // This is a link to an external opml resource
  200.                // Try to import that ressource as a folder
  201.                res = preLoadLink( url,text,description,parent,folderLinks );
  202.                if(res) numItems++;
  203.              }
  204.              else
  205.              {
  206.                // Find a standard url ?
  207.                // Import as standard bookmark
  208.                if(duplicate || !bmUtils.isBookmarked(urlRes,url)) {
  209.                  var shortcutUrl = element.@yns::keywords.toString();
  210.                  res = bmUtils.createBookmark(text,url,shortcutUrl,
  211.                                               description,
  212.                                               null);
  213.                  numItems++;
  214.                }
  215.              }
  216.            } break;
  217.  
  218.            case "rss" : {
  219.              var url = element.@htmlUrl.toString();
  220.              if(duplicate || !bmUtils.isBookmarked(urlRes,url))
  221.              {
  222.                var name    = element.@title.toString();
  223.                var urlfeed = element.@xmlUrl.toString();
  224.                res = bmUtils.createLivemark(name,url,urlfeed,
  225.                                             description,
  226.                                             null); 
  227.                numItems++;
  228.              }
  229.            } break;
  230.  
  231.            default: {
  232.               /*
  233.                * Handle special types
  234.                */
  235.            
  236.               if(element.@yns::type == "separator") {
  237.                 // Add separator only if items have been inserted
  238.                 // before. This prevent useless separators to be
  239.                 // displayed.
  240.                 if(numItems>0)
  241.                    res = bmUtils.createSeparator();
  242.                    
  243.                 break;
  244.               } 
  245.  
  246.               if(element.@yns::type == "folder") {
  247.                 // Add as folder only if it is empty
  248.                 // Because non empty <outline>'s are handled below
  249.                 if(element.outline.length()==0)
  250.                    res = importAsFolder(element,text,description,parent,{links:folderLinks});    
  251.                    
  252.                 break;
  253.               } 
  254.               
  255.            } break;
  256.          }
  257.  
  258.          if(res) {
  259.             var index = parentContainer.IndexOf(res);
  260.             if(index == -1)
  261.                parentContainer.AppendElement(res);
  262.          }
  263.          // If there is <outline> childs then include as folder
  264.          if(element.outline.length()>0) {
  265.             res = importAsFolder(element,text,description,parent,{links:folderLinks});
  266.             if(res) {
  267.               var index = parentContainer.IndexOf(res);
  268.               if(index == -1)
  269.                  parentContainer.AppendElement(res);
  270.             }
  271.          }
  272.        }
  273.      }
  274.    },
  275.  
  276.   /*
  277.    * export 'root'  folder to opml xmlObject
  278.    */
  279.    _export : function( opml, root )
  280.    {
  281.      var bmUtils = this._bmUtils;
  282.      var yns     = this._yns;
  283.      var owner   = this._owner;
  284.      
  285.      const RDF  = bmUtils.RDF;
  286.      const RDFC = bmUtils.RDFC; 
  287.  
  288.      const nsIRDFResource = Components.interfaces.nsIRDFResource;
  289.  
  290.      const urlRes     = bmUtils.getArc("URL");
  291.      const nameRes    = bmUtils.getArc("Name");
  292.      const descRes    = bmUtils.getArc("Description");
  293.      const keywordRes = bmUtils.getArc("ShortcutURL");
  294.      const iconRes    = bmUtils.getArc("Icon");
  295.      const feedRes    = bmUtils.getArc("FeedURL");
  296.      const dateRes    = bmUtils.getArc("BookmarkAddDate");
  297.  
  298.      var ds = bmUtils.BKMS;  
  299.  
  300.      var foldersets = [[opml,root]];
  301.      var folderset  = null;  
  302.           
  303.      var nodetree = [];
  304.  
  305.      while(foldersets.length>0)
  306.      {
  307.        folderset = foldersets.shift();
  308.  
  309.        var folder = folderset[0];
  310.        var parent = folderset[1];
  311.  
  312.        var parentContainer = bmUtils.getContainer(parent);
  313.        var elements        = parentContainer.GetElements();
  314.        
  315.        var subtree = [];
  316.        
  317.        while (elements.hasMoreElements()) 
  318.        {
  319.          var res = elements.getNext().QueryInterface(nsIRDFResource);
  320.  
  321.          var separator = false;
  322.          var isFolder  = false;
  323.          var element   = null;
  324.  
  325.          var type = bmUtils.getType(res);
  326.  
  327.          switch(type)
  328.          {
  329.            case "Bookmark": {
  330.                 var url      = bmUtils.getProperty(res,urlRes);              
  331.                 var keywords = bmUtils.getProperty(res,keywordRes);  
  332.                 if(keywords)
  333.                   element = <outline type="link" link={url} xmlns:yns={YOONO_NS}
  334.                                      yns:keywords={keywords}/>;
  335.                 else
  336.                   element = <outline type="link" url={url}/>;
  337.               }
  338.               break;
  339.  
  340.            case "Livemark": {
  341.                 var htmlUrl = bmUtils.getProperty(res,urlRes);              
  342.                 var xmlUrl  = bmUtils.getProperty(res,feedRes);
  343.                 var title   = bmUtils.getProperty(res,nameRes); 
  344.                 element     = <outline htmlUrl={htmlUrl} 
  345.                                       xmlUrl={xmlUrl}
  346.                                       title={title}
  347.                                       language="unknown"
  348.                                       type="rss"/>;
  349.               }
  350.               break;
  351.  
  352.            case "Folder": 
  353.            case "ToolbarFolder":
  354.               element = <outline yns:type="folder" xmlns:yns={YOONO_NS}/>;
  355.               foldersets.push([element,res]);
  356.               break;
  357.  
  358.            case "BookmarkSeparator":
  359.               element = <outline yns:type="separator" xmlns:yns={YOONO_NS}/>;
  360.               separator = true;
  361.               break;
  362.          }
  363.  
  364.          if(element) 
  365.          {           
  366.            element.@text = bmUtils.getProperty(res,nameRes);
  367.  
  368.            if(!separator) 
  369.            {
  370.              var description = bmUtils.getProperty(res,descRes);
  371.              if(description)  
  372.                 element.@description = description;  
  373.            }
  374.  
  375.            subtree.push([element,folder]); 
  376.          }
  377.        }
  378.  
  379.        nodetree = nodetree.concat(subtree.reverse()); 
  380.      }
  381.  
  382.      while(nodetree.length>0)
  383.      {
  384.        var node = nodetree.pop();
  385.        node[1].* += node[0];
  386.      }
  387.  
  388.      return opml;
  389.    },
  390.  
  391.    /*
  392.     * Import opml from external link
  393.     * XXX Should be asynchronous !
  394.     */
  395.     _importLink : function( uri ) 
  396.     {
  397.      try {
  398.  
  399.        this._bmUtils.error("yoono:opml","Loading remote file\n"+uri.spec);
  400.  
  401.        var channel = this._ioSrvc.newChannelFromURI( uri )
  402.                           .QueryInterface(Components.interfaces.nsIChannel);
  403.                           
  404.        var input = channel.open();
  405.        var sis   = Components.classes["@mozilla.org/scriptableinputstream;1"]
  406.                      .createInstance(Components.interfaces.nsIScriptableInputStream);
  407.  
  408.        sis.init(input); 
  409.        var buffer = sis.read(sis.available());
  410.  
  411.        input.close();
  412.  
  413.        //------------
  414.        // Parse buffer
  415.        // Use DOM parser for validating xml
  416.        //------------
  417.        var parser = new DOMParser();
  418.        var xmldoc = parser.parseFromString(buffer,"text/xml");
  419.  
  420.        var root = xmldoc.documentElement;
  421.        if ((root.tagName == "parsererror") ||
  422.            (root.namespaceURI == "http://www.mozilla.org/newlayout/xml/parsererror.xml"))
  423.        {
  424.          throw(this.getString("xmlparsererror"));
  425.        }
  426.  
  427.        // Get the opml node from it
  428.        var xmlnode = xmldoc.getElementsByTagName("opml")[0];
  429.        if(xmlnode) 
  430.        {
  431.          var xmlstring = new XMLSerializer().serializeToString(xmlnode);
  432.          return (new XML(xmlstring)).body;
  433.        }
  434.  
  435.      } catch(e) {
  436.        this._bmUtils.error("yoono:opml:",e);
  437.      }
  438.      return null; 
  439.     },
  440.  
  441.    /*
  442.     * Create an opml header
  443.     */
  444.     createOpmlHeader : function( title,desc,ownerName,ownerEmail,ownerId ) 
  445.     {
  446.       var date = (new Date()).toUTCString();
  447.       var opmlhead = 
  448.           <head>
  449.             <title>{title}</title>
  450.             <dateCreated>{date}</dateCreated>
  451.           </head>;
  452.  
  453.       if(desc)
  454.          opmlhead.* += <description>{desc}</description>;
  455.  
  456.       if(ownerName)
  457.          opmlhead.* += <ownerName>{ownerName}</ownerName>;
  458.  
  459.       if(ownerEmail)
  460.          opmlhead.* += <ownerEmail>{ownerEmail}</ownerEmail>;
  461.  
  462.       if(ownerId)
  463.          opmlhead.* += <ownerId>{ownerId}</ownerId>;
  464.              
  465.       return opmlhead;
  466.     },
  467.  
  468.    /*
  469.     * Export bookmarks to OPML2 format
  470.     */
  471.    exportBookmarks : function ( ownerName, ownerEmail, ownerId ) 
  472.    {
  473.      var bmUtils = this._bmUtils;
  474.  
  475.      var opml   = <opml version="2.0" xmlns:yns={YOONO_NS}/>;
  476.      var bmRoot = bmUtils.getRoot();
  477.  
  478.      var title = bmUtils.getPropertyByName(bmRoot,"Name");
  479.      var desc  = bmUtils.getPropertyByName(bmRoot,"Description");
  480.  
  481.      opml.* += this.createOpmlHeader(title,desc,ownerName,ownerEmail,ownerId);
  482.      opml.* += this._export(<body/>,bmRoot);
  483.      return opml;
  484.    }, 
  485.  
  486.    /*
  487.     * Import bookmarks from OPML2 format
  488.     */
  489.    importBookmarks : function ( opml, aBookmarkFolder, baseURI )
  490.    {
  491.      if(!aBookmarkFolder)
  492.          aBookmarkFolder = this._bmUtils.getRoot();     
  493.     
  494.      this._resourcesLinks = [];
  495.                
  496.      this._bmUtils.beginUpdateBatch(); 
  497.    
  498.      var except;
  499.      
  500.      try {
  501.  
  502.        var baseLinks = null;
  503.        var yns       = this._yns;
  504.        
  505.        if(baseURI) {
  506.           baseLinks = new ynListOfLinks(baseURI);
  507.           baseLinks.append(baseURI);
  508.        }
  509.  
  510.        // Import current node;
  511.        this._import(opml.body,aBookmarkFolder,baseLinks);
  512.  
  513.        // Import remote links
  514.        while( this._resourcesLinks.length>0 ) 
  515.        {
  516.          var resourceLink = this._resourcesLinks.shift();
  517.          var links        = resourceLink[0];
  518.          var resource     = resourceLink[1];
  519.  
  520.          opml    = this._importLink(links.baseURI);
  521.          this._import(opml,resource,links);
  522.        }
  523.      } catch(ex) {
  524.        except = ex;
  525.      }
  526.  
  527.      this._bmUtils.flush();
  528.      this._bmUtils.endUpdateBatch();
  529.      
  530.      if(except)
  531.         throw except;
  532.    }
  533.  };
  534.  
  535.